
/*    This file is part of the managarm operating system.
 *   Copyright (C) 2007, 2008, 2009  Alexander van der Grinten
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. */

import java.io.*;
import java.util.*;
import java.util.LinkedList;

import org.managarm.jmanacclib.core.*;
import org.managarm.jmanacclib.frontend.korona.*;
import org.managarm.jmanavalib.utils.*;

import ast.*;

public class JKorCompiler {
	// forces a rebuild of the source code
	private static boolean argForce;
	// destination and source arguments
	private static String argSource;
	private static String argDest;
	// base directory
	private static String argDirectory;
	// global environment
	private static KorEnvironment environment;
	
	private static LinkedList<String> argHeaders
		= new LinkedList<String>();
	
	private final static AstRoot syntaxTree = new AstRoot();
	
	public static void main(String[] args) {
		try {
			environment = new KorEnvironment();
			
			parseArguments(args);
			
			// set the current working directory
			environment.workingDirectory = argDirectory;
			
			// parse all header files
			final Iterator<String> headers = argHeaders.iterator();
			while(headers.hasNext())
				environment.parseFile(syntaxTree,
						environment.findUnit(null, -1, headers.next()));
			
			// parse the input file
			environment.parseFile(syntaxTree,
					environment.findUnit(null, -1, argSource));
			
			// determine the output file path
			final File outpath = new File(argDest);
			String outfname = argDest;
			if(argDirectory != null && outpath.isAbsolute() == false)
				outfname = argDirectory + File.separator + argDest;
			final File outfile = new File(outfname);
			
			// check whether we have to rebuild the source code
			boolean rebuild = false;
			if(argForce == true || outfile.exists() == false)
				rebuild = true;
			final Iterator<String> inciterator
					= environment.includeFiles.iterator();
			while(rebuild == false && inciterator.hasNext()) {
				final File incfile = new File(inciterator.next());
				if(incfile.lastModified() > outfile.lastModified())
					rebuild = true;
			}
			if(rebuild == false)
				return;
			
			System.out.println("Rebuilding " + outfile.getCanonicalPath());
			
			// compile the syntax tree to manacode
			final VaImage image = new VaImage();
			final KorCompiler compiler = new KorCompiler(syntaxTree, image);
			compiler.build();
				
			// write the image to the output file
			final OutputStream out = new FileOutputStream(outfile);
			final VaWriter writer = new VaWriter(image);
			writer.write(out);
			out.close();
		}catch (IOException e) {
			// we could not open one of the files, exit
			System.err.println("Could not read/write file: " + e.getMessage());
			System.exit(-1);
		}catch(CclibException e) {
			if(System.getProperty("jmanacclib.debug") != null)
				e.printStackTrace();
			else
				System.err.println(e.getMessage());
			System.exit(-1);
		}catch(ValibException e) {
			if(System.getProperty("jmanacclib.debug") != null)
				e.printStackTrace();
			else
				System.err.println("Unhandled exception: "
						+ e.getClass().getName() + ": " + e.getMessage());
			System.exit(-1);
		}
	}

	private static void parseArguments(String[] args) throws CclibException {
		int pointer = 0;
		while(pointer < args.length) {
			if(args[pointer].equals("-force")) {
				argForce = true;
				pointer += 1;
			}else if(args[pointer].equals("-base")) {
				argDirectory = args[pointer + 1];
				pointer += 2;
			}else if(args[pointer].equals("-source")) {
				argSource = args[pointer + 1];
				pointer += 2;
			}else if(args[pointer].equals("-dest")) {
				argDest = args[pointer + 1];
				pointer += 2;
			}else if(args[pointer].equals("-header")) {
				argHeaders.add(args[pointer + 1]);
				pointer += 2;
			}else if(args[pointer].equals("-define")) {
				environment.prepDefine(args[pointer + 1]);
				pointer += 2;
			}else if(args[pointer].equals("-include")) {
				environment.includePath.add(args[pointer + 1]);
				pointer += 2;
			}else if(args[pointer].equals("-import")) {
				environment.libraries.put(args[pointer + 1],
						args[pointer + 2]);
				pointer += 3;
			}else{
				throw new CclibException("Invocation error: Illegal " +
						"command line argument: " + args[pointer]);
			}
		}
	}
}
